package com.weasing.res.dao.base.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.weasing.res.dao.base.IBaseDao;
import com.weasing.res.utils.PageBean;
import com.weasing.res.utils.StringUtil;

/**
 * 通用dao
 * 
 * @author 黄龙
 *
 * @param <T>
 */
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> {
	// 通过反射获得调用对象的class类型
	private Class<T> entityClass;
	
	@Resource
	public void setMySessionFactory(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
	
	//用构造器里面或者调用之类的 模板对象的class
	public BaseDaoImpl() {
		ParameterizedType superclass = (ParameterizedType) this.getClass().getGenericSuperclass();
		// 用构造器得到调用这个类的类名class并且复制给 成员变量entityClass
		Type[] actualTypeArguments = superclass.getActualTypeArguments();
		entityClass = (Class<T>) actualTypeArguments[0];
	}
	
	public void save(T entity) {
		this.getHibernateTemplate().save(entity);
	}
	
	public void delete(T entity) {
		this.getHibernateTemplate().delete(entity);
	}
	
	public void update(T entity) {
		this.getHibernateTemplate().update(entity);
	}

	public T findById(Serializable id) {
		return this.getHibernateTemplate().get(entityClass, id);
	}

	public List<T> findAll() {
		String hql = "FROM " + entityClass.getSimpleName();
		return (List<T>) this.getHibernateTemplate().find(hql);
	}

	//执行更新queryName 是domain.xml里面的  query标签的名字
	public void ececuteUpdate(String queryName, Object... objects) {
		Session session = this.getSessionFactory().getCurrentSession();
		Query query = session.getNamedQuery(queryName);
		//为hql语句的?赋值
		int i=0;
		for (Object object : objects) {
			query.setParameter(i++,object);
		}
		//执行更新
		query.executeUpdate();
	}

	public void saveOrUpdate(T entity) {
		this.getHibernateTemplate().saveOrUpdate(entity);
	}

	// 通过当前页和显示总数 查询分页信息
	public void pageQuery(PageBean pageBean) {
		//已知数据
		int currentPage = pageBean.getCurrentPage();
		int pageSize = pageBean.getPageSize();
		DetachedCriteria detachedCriteria = pageBean.getDetachedCriteria();
		//查询total--总数量
		//指定发送sql的形式 count(*)
		detachedCriteria.setProjection(Projections.rowCount());
		List<Long> countList = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
		Long count = countList.get(0);
		int totalCount = count.intValue();
		// pageBean = new PageBean(currentPage, totalCount);
		// pageBean.setDetachedCriteria(DetachedCriteria.forClass(entityClass));
		pageBean.setTotal(totalCount);
		int totalPage = (totalCount + pageSize - 1) / pageSize;
		pageBean.setTotalPage(totalPage);

		//查询rows---当前页需要的数据集合
		// 清空离线查询select * from limit
		detachedCriteria.setProjection(null);
		// 指定排序的方式是 降序排列
		detachedCriteria.addOrder(Order.desc("id"));
		int fristResult = (currentPage-1)*pageSize;
		int maxResult = pageSize;
		List rows = this.getHibernateTemplate().findByCriteria(detachedCriteria,fristResult,maxResult);
		pageBean.setRows(rows);
	}

	/**
	 * 查询表中数据的数据
	 * 
	 * @author 黄龙
	 */
	public Integer findCount() {
		String hql = "select count(*)  from " + entityClass.getSimpleName();
		Session session = this.getSessionFactory().getCurrentSession();
		Query query = session.createQuery(hql);
		Integer i = ((Long) query.iterate().next()).intValue();
		return i;
	}

	/**
	 * 通过字段名和属性找到对应的个数
	 * 
	 * 
	 * 
	 * @author 黄龙
	 */
	public Integer findCountByField(Map<String, Object> map) {
		DetachedCriteria detachedCriteria = DetachedCriteria
				.forClass(entityClass);
		detachedCriteria.setProjection(Projections.rowCount());
		if (null != map) {
			Iterator it = map.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				String key = (String) entry.getKey();
				Object value = (Object) entry.getValue();
				if (StringUtil.isNotNulls(key) || null != value) {
					detachedCriteria.add(Restrictions.eq(key, value));
				}
			}
		}
		List<Long> countList = (List<Long>) this.getHibernateTemplate()
				.findByCriteria(detachedCriteria);
		detachedCriteria.setProjection(null);
		Long count = countList.get(0);
		int i = count.intValue();
		return i;
	}

	public List<T> findAllByParentId(Integer parentId) {
		String hql = "FROM " + entityClass.getSimpleName()
				+ " p WHERE p.parent IS " + parentId;
		Session session = this.getSessionFactory().getCurrentSession();
		Query query = session.createQuery(hql);
		return query.list();
	}

	/**
	 * 查所有
	 */
	public List<T> findAllByCriteria() {
		DetachedCriteria detachedCriteria = DetachedCriteria
				.forClass(entityClass);

		List<T> findByCriteria = (List<T>) this.getHibernateTemplate()
				.findByCriteria(detachedCriteria);
		return findByCriteria;
	}

	/**
	 * 模糊查询
	 * 
	 * @author 黄龙
	 */
	@Override
	public void pageQuery(PageBean pageBean, Map<String, Object> map) {
		if (null != map) {
			Iterator it = map.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				String key = (String) entry.getKey();
				Object value = (Object) entry.getValue();
				if (StringUtil.isNotNulls(key) || null != value) {
				DetachedCriteria detachedCriteria = pageBean
						.getDetachedCriteria();
					if(value instanceof String){
						detachedCriteria.add(Restrictions.like(key, "%" + value + "%"));
					}if(value instanceof Integer){
						detachedCriteria.add(Restrictions.eq(key, value));
					} else {
						detachedCriteria
								.add(Restrictions.like(key, "%" + value + "%"));
					}
				}
			}
		}
		pageQuery(pageBean);
	}

	/**
	 * 根据字段名字找对象
	 * 
	 * @author 黄龙
	 * 
	 */
	@Override
	public List<T> findByField(Map<String, Object> map) {

		DetachedCriteria detachedCriteria = DetachedCriteria
				.forClass(entityClass);
		// detachedCriteria.setProjection(Projections.rowCount());
		if (null != map) {
			Iterator it = map.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				String key = (String) entry.getKey();
				Object value = (Object) entry.getValue();
				if (StringUtil.isNotNulls(key) || null != value) {
					detachedCriteria.add(Restrictions.eq(key, value));
				}
			}
		}
		List list = this.getHibernateTemplate()
				.findByCriteria(detachedCriteria);
		return list;
	}

	/**
	 * 
	 * gourd by 字段然后返回list
	 * 
	 * @author 黄龙
	 * 
	 */
	// TODO
}
